package com.lmpop.frame.util;

import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ParseXmlQuery
{
  public String fileStr;
  public FileIO fileIo;
  public ArrayList tagList;
  public Config config;

  public ParseXmlQuery()
  {
    this.fileIo = new FileIO();
    this.tagList = new ArrayList();
    this.config = new Config();
    this.config.init("config.properties");
  }

  public String getSqlStringById(String id, Map map) {
    parseSqlMap(id);
    initTagList(id);
    String sql = getSqlById(id);
    return createOpeateSql(sql, map);
  }

  public void parseSqlMap(String sqlid) {
    String sqlMapPath = InitProject.classPath() + this.config.getString("sqlMapConfigName");
    String sqlMapStr = FileIO.LoadFile(sqlMapPath);

    Pattern p = Pattern.compile("<sqlMap resource=\"[[a-zA-Z_]+/]+[a-zA-Z_]+.xml\"\\s*/>");
    Matcher m = p.matcher(sqlMapStr);
    ArrayList mapList = new ArrayList();
    while (m.find()) {
      String xmlClassPath = m.group().replace("<sqlMap resource=", "").replace("/>", "").replace("\"", "").replace(" ", "");
      String instr = FileIO.LoadFile(InitProject.classPath() + xmlClassPath);
      if (instr.indexOf("id=\"" + sqlid + "\"") > -1)
        this.fileStr = instr;
    }
  }

  public String createOpeateSql(String sql, Map nMap)
  {
    if (sql.equals("")) throw new RuntimeException("sqlId not found!");
    String tagName = "isNotNull";
    while (checkTag(tagName, sql)) {
      String isNotNull = getTagBody(tagName, sql);
      Hashtable isNotNullMap = getTagParaMap(isNotNull, tagName);
      String sqlContent = getTagContent(isNotNull, tagName);

      String property = ""; String prepend = "";
      if (isNotNullMap.get("property") != null) property = isNotNullMap.get("property").toString();
      if (isNotNullMap.get("prepend") != null) prepend = isNotNullMap.get("prepend").toString();

      StringBuffer tempSql = new StringBuffer();
      if (nMap.get(property) != null) {
        tempSql.append(" " + prepend + " ");
        sqlContent = mapValueToSql(sqlContent, nMap);
        tempSql.append(sqlContent);
      }

      sql = sql.replace(isNotNull, tempSql.toString());
    }
    sql = mapValueToSql(sql, nMap);
    sql = sql.replace("\n", "");
    return sql;
  }

  public String mapValueToSql(String sql, Map map)
  {
    if (map == null) return sql;
    Iterator it = map.keySet().iterator();
    String name = ""; String value = "";
    Hashtable sqlMap = new Hashtable();
    while (it.hasNext()) {
      name = it.next().toString();
      if (map.get(name) != null) {
        value = map.get(name).toString();
      }
      if (sql.indexOf("#" + name + "#") > -1) sql = sql.replace("#" + name + "#", "'" + value + "'");
      if (sql.indexOf("$" + name + "$") <= -1) continue; sql = sql.replace("$" + name + "$", value);
    }
    return sql;
  }

  public String getSqlById(String id) {
    return getFieldById("sql", id);
  }

  public String getFieldById(String fieldName, String id) {
    String sql = "";
    if ((this.tagList != null) && (this.tagList.size() > 0)) {
      Hashtable tagMap = new Hashtable();
      for (int i = 0; i < this.tagList.size(); i++) {
        tagMap = (Hashtable)this.tagList.get(i);
        if (getHashtableKey(tagMap).equals(id)) {
          sql = getHashtableField(tagMap, fieldName);
        }
      }
    }
    return sql;
  }

  public String getHashtableField(Hashtable map, String fieldName) {
    if (map == null) return "";
    Iterator it = map.keySet().iterator();
    String key = ""; String fieldValue = "";
    Hashtable sqlMap = new Hashtable();
    while (it.hasNext()) {
      key = (String)it.next();
      sqlMap = (Hashtable)map.get(key);
    }
    if (sqlMap.get(fieldName) != null) fieldValue = sqlMap.get(fieldName).toString();
    return fieldValue;
  }

  public String getHashtableKey(Hashtable map) {
    if (map == null) return "";
    Iterator it = map.keySet().iterator();
    String key = "";
    while (it.hasNext()) {
      key = (String)it.next();
    }
    return key;
  }

  public void initTagList(String sqlid) {
    String tagName = "select";
    while (checkTag(tagName, this.fileStr)) {
      String tagStr = getTagBody(tagName, this.fileStr);
      this.fileStr = this.fileStr.replace(tagStr, "");
      String tagId = getTagField("id", tagStr, tagName);
      if (tagId.equals(sqlid)) {
        Hashtable conMap = getTagParaMap(tagStr, tagName);
        conMap.remove("id");
        conMap.put("sql", getTagContent(tagStr, tagName));

        Hashtable paraMap = new Hashtable();
        paraMap.put(tagId, conMap);
        this.tagList.add(paraMap);
      }
    }
  }

  public String getTagField(String field_name, String tagStr, String tagName) {
    Hashtable paraMap = getTagParaMap(tagStr, tagName);
    String tagField = "";
    if (paraMap.get(field_name) != null) {
      tagField = paraMap.get(field_name).toString();
    }
    return tagField;
  }

  public String getTagContent(String tagStr, String tagName) {
    String tagParaStr = getTagPara(tagStr, tagName);
    String tempStr = tagStr.replace(tagParaStr, "").replace("</" + tagName + ">", "");
    tempStr = tempStr.replace("<![CDATA[", "").replace("]]>", "").trim();
    return tempStr;
  }

  public Hashtable getTagParaMap(String tagStr, String tagName) {
    if (tagStr.equals("")) return null;
    Hashtable paraMap = new Hashtable();
    String tagParaStr = getTagPara(tagStr, tagName);
    String tempStr = tagParaStr.replace("<" + tagName, "").replace(">", "").replace("'", "").replace("\"", "");

    String[] paraVal = tempStr.split(" ");
    if (paraVal.length > 0) {
      for (int i = 0; i < paraVal.length; i++) {
        if (!paraVal[i].equals("")) {
          String[] val = paraVal[i].split("=");
          if ((val.length <= 1) || (val[0].equals(""))) continue; paraMap.put(val[0], val[1]);
        }
      }
    }
    return paraMap;
  }

  public String getTagPara(String tagStr, String tagName) {
    if (tagStr.equals("")) return null;
    int start = tagStr.indexOf("<" + tagName);
    int end = tagStr.indexOf(">") + 1;
    String tagParaStr = "";
    if (end > start) tagParaStr = tagStr.substring(start, end);
    return tagParaStr;
  }

  public String getFileStr() {
    return this.fileStr;
  }

  public boolean checkTag(String tagName, String str)
  {
    return str.indexOf("<" + tagName) > -1;
  }

  public String getTagBody(String tagName, String sqlStr)
  {
    String endTag = "</" + tagName + ">";
    int start = sqlStr.indexOf("<" + tagName);
    int end = sqlStr.indexOf(endTag);
    String sonTagStr = "";
    if (end > start) {
      sonTagStr = sqlStr.substring(start, end + endTag.length());
    }
    return sonTagStr;
  }
}